home *** CD-ROM | disk | FTP | other *** search
/ Speccy ClassiX 1998 / Speccy ClassiX 98.iso / amiga_system / the_aminet / dev / gcc / ixemulsrc.lha / ixemul-41.4 / library / _main.c < prev    next >
C/C++ Source or Header  |  1995-05-20  |  7KB  |  271 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Library General Public
  16.  *  License along with this library; if not, write to the Free
  17.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  _main.c,v 1.1.1.1 1994/04/04 04:30:43 amiga Exp
  20.  *
  21.  *  _main.c,v
  22.  * Revision 1.1.1.1  1994/04/04  04:30:43  amiga
  23.  * Initial CVS check in.
  24.  *
  25.  *  Revision 1.3  1992/08/09  20:41:54  amiga
  26.  *  change to use 2.x header files by default
  27.  *  add option to ignore global environment (ix.ix_ignore_global_env).
  28.  *
  29.  *  Revision 1.2  1992/07/04  19:10:06  mwild
  30.  *  add call to ix_install_sigwinch().
  31.  *
  32.  * Revision 1.1  1992/05/17  21:01:29  mwild
  33.  * Initial revision
  34.  *
  35.  *
  36.  */
  37.  
  38. #define KERNEL
  39. #include "ixemul.h"
  40. #include "kprintf.h"
  41.  
  42. #include <dos/var.h>
  43. #include <workbench/startup.h>
  44. #include <dirent.h>
  45.  
  46. extern  struct ExecBase       *SysBase;
  47.  
  48. static char **
  49. __get_environ (void)
  50. {
  51.   static char *endmarker = 0;
  52.   char **env = &endmarker;
  53.   DIR *dp;
  54.   struct dirent *de;
  55.   int num_env, num_local = 0;
  56.   char **cp;
  57.  
  58.   /* 2.0 local environment overrides 1.3 global environment */
  59.       struct Process *me = (struct Process *) FindTask (0);
  60.       struct LocalVar *lv, *nlv;
  61.  
  62.       /* count total number of local variables (skip aliases) */
  63.       for (num_local = 0, 
  64.          lv  = (struct LocalVar *) me->pr_LocalVars.mlh_Head;
  65.        nlv = (struct LocalVar *) lv->lv_Node.ln_Succ;
  66.        lv  = nlv)
  67.     if (lv->lv_Node.ln_Type == LV_VAR)
  68.       num_local ++;
  69.       
  70.       if (cp = (char **) syscall (SYS_malloc, (num_local + 1) * 4))
  71.     {
  72.       env = cp;
  73.  
  74.       for (lv  = (struct LocalVar *) me->pr_LocalVars.mlh_Head;
  75.            nlv = (struct LocalVar *) lv->lv_Node.ln_Succ;
  76.            lv  = nlv)
  77.         {
  78.           /* I'm not interested in aliases, really not ;-)) */
  79.           if (lv->lv_Node.ln_Type != LV_VAR)
  80.             continue;
  81.         
  82.           /* NAME=CONTENTS\0 */
  83.           *cp = (char *) syscall (SYS_malloc, (strlen (lv->lv_Node.ln_Name) 
  84.                            + 1 + lv->lv_Len + 1));
  85.           if (*cp)
  86.         sprintf (*cp, "%s=%*.*s", lv->lv_Node.ln_Name, 
  87.              lv->lv_Len, lv->lv_Len, lv->lv_Value);
  88.  
  89.           else
  90.         break;
  91.  
  92.           cp ++;
  93.         }
  94.  
  95.       *cp = 0;
  96.     }
  97.       else
  98.     num_local = 0;
  99.  
  100.   if (ix.ix_ignore_global_env)
  101.     return env;
  102.  
  103.   /* now go for global variables */
  104.   
  105.   if (dp = (DIR *) syscall (SYS_opendir, "ENV:"))
  106.     {
  107.       /* first count how many entries we have */
  108.       for (num_env = 0; readdir (dp); num_env++) ;
  109.       
  110.       /* skip . and .. */
  111.       syscall (SYS_rewinddir, dp);
  112.       if ((de = (struct dirent *) syscall (SYS_readdir, dp)) 
  113.       && de->d_namlen == 1 && de->d_name[0] == '.' && --num_env &&
  114.       (de = (struct dirent *) syscall (SYS_readdir, dp)) 
  115.       && de->d_namlen == 2 && de->d_name[0] == '.' && de->d_name[1] == '.')
  116.     {
  117.       num_env --;
  118.       de = (struct dirent *) syscall (SYS_readdir, dp);
  119.     }
  120.  
  121.       if (num_local)
  122.     {
  123.       /* only (!) in this case is `env' allocated and not static */
  124.       char **tmp = (char **) syscall (SYS_realloc, 
  125.                       env, (num_local + num_env + 1) * 4);
  126.       if (tmp)
  127.         {
  128.           cp = tmp + (cp - env);
  129.           env = tmp;
  130.         }
  131.       else
  132.         /* out of memory !!! */
  133.         return &endmarker;
  134.     }
  135.       else
  136.     {
  137.       if (cp = (char **) syscall (SYS_malloc, (num_env + 1) * 4))
  138.         env = cp;
  139.       else
  140.         /* out of memory !!! */
  141.         return &endmarker;
  142.     }
  143.       
  144.  
  145.       for (;de; de = (struct dirent *) syscall (SYS_readdir, dp))
  146.     {
  147.       struct stat stb;
  148.       int len = 0;
  149.       char envfile[MAXPATHLEN];
  150.  
  151.       /* If this variable already exists locally, skip it */
  152.       if (FindVar (de->d_name, GVF_LOCAL_ONLY))
  153.         continue;
  154.  
  155.       /* Don't include variables with funny names, and don't include
  156.          multiline variables either, they totally confuse ksh.. */
  157.       if (index (de->d_name, '.'))
  158.         continue;
  159.  
  160.       sprintf (envfile, "ENV:%s", de->d_name);
  161.  
  162.       if (stat (envfile, &stb) == 0)
  163.         {
  164.           len = stb.st_size;
  165.           /* skip directories... shudder */
  166.           if (! S_ISREG (stb.st_mode))
  167.             continue;
  168.         }
  169.  
  170.       /* NAME=CONTENTS\0 */
  171.       *cp = (char *) syscall (SYS_malloc, 
  172.                   de->d_namlen + 1 + len + 1);
  173.       if (*cp)
  174.         {
  175.           int written = sprintf (*cp, "%s=", de->d_name);
  176.           int fd;
  177.  
  178.           if (len)
  179.         {
  180.           fd = open (envfile, 0);
  181.           if (fd >= 0)
  182.             {
  183.               written += read (fd, *cp + written, len);
  184.               (*cp)[written] = 0;
  185.               if ((*cp)[--written] == '\n')
  186.             (*cp)[written] = 0;
  187.               close (fd);
  188.             }
  189.             
  190.           /* now filter out those multiliners (that is, 
  191.              variables containing \n, you can have variables
  192.              as long as want, but don't use \n... */
  193.           if (index (*cp, '\n'))
  194.             {
  195.               syscall (SYS_free, *cp);
  196.               continue;
  197.             }
  198.         }
  199.         }
  200.       else
  201.         break;
  202.  
  203.       cp ++;
  204.     }
  205.  
  206.       *cp = 0;
  207.  
  208.       syscall (SYS_closedir, dp);
  209.       
  210.       return env;
  211.     }
  212.   else
  213.     /* `panic!', no ENV: logical ! */
  214.     return &endmarker;
  215. }
  216.  
  217.  
  218. /* smells abit kludgy I know.. but can live with quite few variables in
  219.  * the user area 
  220.  */
  221.  
  222. int
  223. _main (union { char *_aline; struct WBStartup *_wb_msg; } a1,
  224.        union { int   _alen;  char *_def_window;         } a2,
  225.        int (* main(int, char **, char **)))
  226. #define aline           a1._aline
  227. #define alen            a2._alen
  228. #define wb_msg          a1._wb_msg
  229. #define def_window      a2._def_window
  230. {
  231.   struct Process        *me             = (struct Process *)SysBase->ThisTask;
  232.   int                   exit_val;
  233.   char                  **argv, **env;
  234.   int                   argc;
  235.  
  236.   KPRINTF (("entered __main()\n"));
  237.   if (! me->pr_CLI)
  238.     {
  239.       /* Workbench programs expect to have their CD where the executed
  240.        * program lives. */
  241.       if (wb_msg->sm_ArgList)
  242.     {
  243.       CurrentDir (wb_msg->sm_ArgList->wa_Lock);
  244.       syscall (SYS__wb_parse, me, wb_msg, def_window);
  245.     }
  246.       /* argc==0: this means, that argv is really a WBenchMsg, not a vector */
  247.       argc = 0;
  248.       argv = (char **) wb_msg;
  249.     }
  250.   else
  251.     {
  252.       /* if we were started from the CLI, alen & aline are valid and
  253.        * should now be split into arguments. This is done by the
  254.        * function "_cli_parse()", which does wildcard expansion if not
  255.        * disabled (see cli_parse.c). */
  256.       _cli_parse (me, alen, aline, &argc, &argv);
  257.     }
  258.  
  259.   env = __get_environ ();
  260.  
  261.   /* this is not really the right thing to do, the user should call
  262.      ix_get_vars2 () to initialize environ to the address of the variable
  263.      in the calling program. However, this setting guarantees that 
  264.      the user area entry is valid for getenv() calls. */
  265.   u.u_environ = &env;
  266.  
  267.   ix_install_sigwinch ();
  268.  
  269.   syscall (SYS_exit, main (argc, argv, env));
  270. }
  271.